#include "net_client.h"
#include "log.h"

namespace edm{
namespace network{
    
net_client_t::net_client_t(const std::string& host, const std::string& port):
        m_host(host), m_port(port), m_started(false), 
        m_callback_handler(0), m_callback_error(0),m_callback_connect(0),
        m_io_work(new boost::asio::io_service::work(m_io_service)),
        m_client_connection(new connection_t(m_io_service, host, port))
{
    logtrace((MYNET, "net_client_t::net_client_t <%s:%s>", m_host.c_str(), m_port.c_str()));
}

net_client_t::~net_client_t()
{
    logtrace((MYNET, "net_client_t::~net_client_t <%s:%s>", m_host.c_str(), m_port.c_str()));
    if(m_started) stop();
    logtrace((MYNET, "net_client_t::~net_client_t <%s:%s>", m_host.c_str(), m_port.c_str()));
}

//! start network client
int net_client_t::start(callback_handler_t cb, callback_error_t cb_err, callback_connect_t cb_ok)
{
    logtrace((MYNET, "net_client_t::start <%s:%s> begin ...", m_host.c_str(), m_port.c_str()));
    if(m_started)
    {
        logwarn((MYNET, "net_client_t::start <%s:%s> already started", m_host.c_str(), m_port.c_str()));
        return 0;
    }
    m_callback_handler = cb;
    m_callback_error = cb_err;
    if(cb_ok) m_callback_connect = cb_ok;
    //! start thread
    
    m_thread.reset(new boost::thread(
    boost::bind(&boost::asio::io_service::run, &m_io_service)));
    
    m_client_connection->start(m_callback_handler, m_callback_error, m_callback_connect);
    //! set flag
    m_started = true;
    
    logtrace((MYNET, "net_client_t::start <%s:%s> end ok.", m_host.c_str(), m_port.c_str()));
    return 0;
}

//! stop network client
int net_client_t::stop()
{
    logtrace((MYNET, "net_client_t::stop <%s:%s> begin ...", m_host.c_str(), m_port.c_str()));
    if(!m_started)
    {
        logwarn((MYNET, "net_client_t::start <%s:%s> already stopped", m_host.c_str(), m_port.c_str()));
        return 0;
    } 
    
    m_io_work.reset();
    m_thread->join();
    m_started = false;
    
    logtrace((MYNET, "net_client_t::stop <%s:%s> stop ok.", m_host.c_str(), m_port.c_str()));
    return 0;
}
   
//! write message
void net_client_t::async_write(COMMANDER command, edm_uint32_t reserved, std::string& body)
{
    logtrace((MYNET, "net_client_t::async_write <%d:%s> begin ...", command, body.c_str()));
    m_client_connection->async_write(command, reserved, body);
    logtrace((MYNET, "net_client_t::async_write <%d:%s> end ok.", command, body.c_str()));
}

//! write message
void net_client_t::async_write(COMMANDER command, edm_uint32_t reserved, const char* body)
{
    logtrace((MYNET, "net_client_t::async_write <%d:%s> begin ...", command, body));
    m_client_connection->async_write(command, reserved, body);
    logtrace((MYNET, "net_client_t::async_write <%d:%s> end ok.", command, body));
}
}}
